home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol330 / gagsdocs.arc / PART3.DOC < prev    next >
Encoding:
Text File  |  1986-06-15  |  22.0 KB  |  432 lines

  1.                                       3-1
  2.  
  3.       The Generic Adventure Game System
  4.       Copyright 1985, 1986 by Mark J. Welch  415-845-2430 (voice)
  5.  
  6.  
  7.       The GAGS source code (briefly explained, not included)
  8.       --------------------
  9.       
  10.       [ The GAGS source code is available to registered users of GAGS 
  11.         for $25; source code purchasers must also sign an agreement not 
  12.         to distribute or share the source code. For information, 
  13.         contact Mark J. Welch, P.O.Box 2409, SF, CA 94126.] 
  14.       
  15.       The Generic Adventure Game System is broken into fourteen 
  16.       "modules," each structured as a Turbo Pascal "include" file.  
  17.       Initially, the entire program was in one source code file. The 
  18.       tremendous size of the parser led to its being broken out as a 
  19.       separate module. Soon, other groups of procedures were also 
  20.       removed from the main program file so that I could edit and print 
  21.       smaller pieces at a time, and so that Turbo could handle the 
  22.       files (Turbo Pascal can only process files up to 64K).  
  23.            As my Programming Methodology professor pointed out four 
  24.       years ago, it is also much easier to track down bugs when you 
  25.       only modify one module at a time. Naturally, I should've started 
  26.       the project by defining the separate modules, and I should have 
  27.       drawn out pseudo-code, so that the program was better structured. 
  28.       These bad habits might explain the 'C' I got in that class....  
  29.  
  30.            The twelve modules are: 
  31.  
  32.       -- the parser (PARSE.MOD); 
  33.       -- the execution module (EXECUTE.MOD) which interprets the 
  34.       user's parsed command line, with three sub-modules EXECSUBS.MOD,
  35.       SPECIALS.MOD, and SAVEREST.MOD; 
  36.       -- the initialization module (INIT.MOD), which zeros out all 
  37.       the arrays and reads the data file;
  38.       -- the declaration module (DECLARE.MOD), which contains all the 
  39.       global type, constant, and variable  declarations;
  40.       -- a command-line parameter checking module (PARAM.MOD);
  41.       -- a title-printing module (TITLE.MOD) which also contains 
  42.       several useful tools; 
  43.       -- a creature-animation module (ANIMATE.MOD), which executes 
  44.       any actions creatures take (i.e. attacking the player);
  45.       -- two tools modules (GENTOOLS.MOD and SPCTOOLS.MOD) which contain 
  46.       procedures and functions used by more than one other module;
  47.       -- a module to describe and list the player's location 
  48.       information (DESCRIBE.MOD);
  49.       -- and the main program (ADVENT.PAS) which INCLUDEs the other 
  50.       modules. 
  51.       
  52.                                       3-2
  53.       
  54.       Summary:
  55.       
  56.       The parser is quite straightforward: it takes a command line 
  57.       string, and breaks it into words; it massages the words, tries to 
  58.       eliminate unimportant words, throws away adjectives if they match 
  59.       following nouns, and locate from one to four important sentence 
  60.       elements: a verb, a noun, a preposition, and an object of the 
  61.       preposition. These are passed back to the main program.  
  62.            The main program immediately 'executes' the user's 
  63.       deciphered command (unless a syntax error was discovered in the 
  64.       parser); the execute module simply decides which verb was used 
  65.       and calls the procedure appropriate to that verb or class of 
  66.       verbs.  
  67.      
  68.            Whenever a change is made to the program, several modules 
  69.       must usually be changed. For example, to add a new field to nouns 
  70.       (say, 'NUKEABLE'), the declaration of the nouns record must be 
  71.       changed to add the field; the initialization procedure must 
  72.       assign it a default value ('true'?) and must also check to see if 
  73.       the noun declaration in the data file changes its 'default' 
  74.       value; and any appropriate changes must also be made to the 
  75.       execute module. In this case, the logical intent would be to also 
  76.       add a verb 'NUKE' and of course also add a procedure in the 
  77.       execute module called 'nuke' with a parameter of what noun to 
  78.       destroy. That verb would have to be added in the initialization 
  79.       module (INIT_VERBS procedure) so the parser recognizes it; and an 
  80.       appropriate check would be made in the nuke procedure to see if 
  81.       conditions are met. Nuke might activate a special, which means 
  82.       the nuke procedure would call the 'special' procedure if the 
  83.       proper conditions are met. 
  84.  
  85.  
  86.                                         Mark J. Welch
  87.                                         P.O. Box 2409
  88.                                         San Francisco CA 94126
  89.                                         (415) 845-2430 (voice)
  90.  
  91.                                       3-3
  92.  
  93.       GAGS - A Generic Adventure Game System 
  94.       Copyright 1985, 1986 by Mark Welch
  95.  
  96.       --------------------------
  97.       In More Detail: The Parser
  98.       --------------------------
  99.          Definition: The PARSER examines each word in an input sentence 
  100.       to determine whether it is a valid part of speech in the context of 
  101.       other words in the sentence.  
  102.  
  103.  
  104.       Background:
  105.           In some software, the input is quite fixed. In spreadsheets or 
  106.       word processors, for example, a fixed list of commands are 
  107.       available, and no general flexibility is permitted (although 
  108.       multiple ways might be offered to accomplish the same task).  
  109.            In some early adventure games, two-word commands were the 
  110.       limit.  "TAKE BOOK" was the way you picked up a book. Sometimes 
  111.       synonyms were offered ("GET", for example). More complex sentences 
  112.       were sometimes permitted ("THROW AXE AT DWARF"), but it's a much 
  113.       easier programming task if the syntax is fixed. For this last 
  114.       reason, the word "the" was a latecomer to adventure games.  
  115.            Of course, what you really want is a way to say "Take the 
  116.       small red key from the second dwarf and put it in the blue box 
  117.       under the rug" and have the program figure out what you want. GAGS 
  118.       can't do that, for several reasons. It can, however, accept some 
  119.       fairly long sentences and concepts more complex than  "THROW AXE." 
  120.            One acquaintance suggested that a really good adventure game 
  121.       should understand a sentence like "Dive under the fallen branch and 
  122.       roll to the left, grabbing the laser pistol as you rise, and sever 
  123.       the dwarf's leg by ricocheting a laser shot off of the pickup's 
  124.       mirror." I'll leave that as an exercise to the reader.  
  125.       
  126.       What does a parser need to do?
  127.  
  128.            A parser breaks up a sentence into parts of speech. Let's 
  129.       think about that for a minute, using the previous sentence as an 
  130.       example.  
  131.        
  132.               "A parser breaks up a sentence into parts of speech."
  133.               /       |   |          |        |      |
  134.       article/ subject^   ^verb      ^object  ^prep  ^obj.of prep
  135.       
  136.            Instantly, most people can recognize the subject and the verb. 
  137.       "Parser" is the noun, and "breaks up" is the verb. Or is "breaks" 
  138.       the verb? "Up" is a preposition...but here it's an adverb. Gee, the 
  139.       English language is complicated.  
  140.            Already we have a problem: some words can serve as multiple 
  141.       parts of speech and can only be parsed by checking context. There 
  142.       are rules to English, but they're complex and filled with 
  143.       exceptions. Many programmers are working hard to develop "Natural 
  144.       Language Interfaces" to computers, so people can get computers to 
  145.       perform complex tasks without having to know how to program a 
  146.       computer. Very few of those "natural language interfaces" can 
  147.       accept a complex sentence, and most -- like GAGS' parser -- limit 
  148.       their knowledge to a certain task so context problems are reduced 
  149.       and the rules can be made more limited.  
  150.       
  151.                                  (continued)
  152.  
  153.                                       3-4
  154.  
  155.                      (the parser, continued)
  156.  
  157.  
  158.            In writing this game, I wasn't interested in AI or complex English 
  159.       or anything like that. I just wanted to allow people to enter 
  160.       understandable sentences, like "put the red key with the blue globe." How 
  161.       to do that?  
  162.            I cheated, to start. The first thing my parser does is strip 
  163.       out extraneous words, words that always (I hope) add no real 
  164.       meaning to a sentence. "The" and "a" are removed. So is "go", since 
  165.       that has no meaning unless it's followed by a direction. GAGS wants 
  166.       a verb to come first in the sentence, and will choke if there isn't 
  167.       one.  
  168.  
  169.  
  170.  
  171.       GAGS' Parser
  172.       ------------
  173.            The Parse procedure first breaks the sentence up into words 
  174.       (an array of strings), arbitrarily counting any non-alphabetic 
  175.       character as a word separator. (Actually, the real check is for 
  176.       ASCII characters from 'A'..'z'.) 
  177.            It then strips out any words which are "extras." A strange 
  178.       effect is that no check is made to see if the sentence really made 
  179.       sense before it was "stripped" of extra words. The sentence 
  180.       
  181.             "The Put the the red the gun the in the the the wooden the bookcase"
  182.  
  183.       becomes
  184.       
  185.             "Put red gun in wooden bookcase."
  186.       
  187.            The parser then immediately begins scanning the sentence, 
  188.       left-to-right.  The first word must be a verb now. If it is, the 
  189.       program moves on to the next word (or exits when it finds no more 
  190.       words). The program expect the second word to be a noun. If it's 
  191.       not a noun, it checks to see if it is an adjective with a noun 
  192.       following it. If neither is true, it checks the possibility that 
  193.       the second word might just be a preposition ("Look in bookcase"). 
  194.       If the second word wasn't a preposition, the third word is checked 
  195.       as a preposition.  The following word(s) is/are again checked as a 
  196.       noun or an adjective-noun pair.  
  197.       
  198.            A more "correct" parser could check for a verb, and then check 
  199.       to make sure that any articles ("the" or "a") are positioned 
  200.       properly with nouns, and that words like "please" or "now" are 
  201.       located logically.  
  202.       
  203.            Four strings are returned from the parser: a verb, a noun, a 
  204.       preposition, and another noun as the object of the preposition. 
  205.       Also, if any error was discovered (a word not recognized, or a 
  206.       missing verb), a boolean variable 'syntax_error' is set to 'true.' 
  207.       
  208.  
  209.  
  210.  
  211.                                       3-5
  212.  
  213.       GAGS - A Generic Adventure Game System 
  214.       Copyright 1985, 1986 by Mark Welch
  215.       
  216.       ---------------------------------
  217.       Possible Source Code Enhancements
  218.       ---------------------------------
  219.  
  220.  
  221.  
  222.       Modifying the Source Code: Some Suggestions
  223.       -------------------------------------------
  224.            There are probably an infinite number of ways you can modify 
  225.       the source code to GAGS to make it a more enjoyable game. In many 
  226.       ways, my original coding was too simple to permit a full-featured 
  227.       game. Changes to the game range from relatively simple and painless 
  228.       additions to some extremely complex modifications which could mean 
  229.       rewriting huge portions of the code. In fact, I'm open-minded 
  230.       enough to realize that some efforts would involve rewriting the 
  231.       entire game or starting from scratch.  
  232.       
  233.       
  234.       Enlarging the Game
  235.       ------------------
  236.       As shipped, GAGS can handle up to 200 rooms, 100 creatures, and 
  237.       100 objects. These limits permit the game to run snugly in a 192K 
  238.       IBM PC, or quite comfortably in a 256K system. If you have more 
  239.       memory than that, you might want to expand these limits. All the 
  240.       changes would be in the declaration module (DECLARE.MOD), where 
  241.       you'd need to simply re-define the first and last numbers of each 
  242.       range (creatures, rooms, and nouns).  
  243.       
  244.  
  245.       "On-Line Help"
  246.       --------------
  247.       One verb you might want to add is "help." A help procedure might 
  248.       do one of several things: it might simply read in a file and 
  249.       display it on the screen; it might prompt for the user's specific 
  250.       help question (or you might patch the parser so the user could 
  251.       type "help scream" or whatever); or it might try to offer 
  252.       context-sensitive help ("The reason you can't go north is that 
  253.       the banshee blocks your way. Banshees often let you pass if you 
  254.       give them yogurt"). 
  255.       
  256.       
  257.       Specials
  258.       --------
  259.       Although several methods of invoking "specials" have been 
  260.       provided, you might want to add more by defining new verbs to 
  261.       activate them. Or, you might modify the "Take" procedure to 
  262.       invoke a special; this would involve a fairly aggressive 
  263.       rewriting of that procedure. You might want to modify the 
  264.       procedures in which a creature is killed to search for text to 
  265.       display, rather than the stock "creature is killed" message; you 
  266.       might even want to leave a dead body in the room after a creature 
  267.       is killed. Keying user-defined verbs to specials would be ideal.
  268.       
  269.                                  (continued)
  270.       
  271.                                       3-6
  272.  
  273.                          (Enhancing GAGS, continued)
  274.                                          
  275.  
  276.       Adding Verbs
  277.       ------------
  278.       Probably the simplest thing to do is add a verb to the game. In 
  279.       the latter stages of development, I was able to add new verbs in 
  280.       about ten minutes, plus the time it took to write a procedure to 
  281.       execute the verb's desired actions. Adding a verb was designed to 
  282.       be the easiest task because I started the game with one verb 
  283.       ("Look") and added new verbs at the rate of about one per night 
  284.       of development and debugging. 
  285.          To add a verb, you must modify the Init_Verbs procedure so 
  286.       that the parser recognizes it as a valid verb, and you must add 
  287.       the new verb to the multiple if..then..else statement in the 
  288.       Execute procedure so that Execute performs the action you desire 
  289.       from the verb's invocation.
  290.          If you want to add synonyms, this involves merely calling 
  291.       whatever procedure already exists. If you want to create a new 
  292.       procedure, you have Execute call it and then write the procedure. 
  293.       I added the "Scream" procedure in this way in a total of fifteen 
  294.       minutes, and then created two synonyms ("shriek" and "shout") in 
  295.       five more minutes. Of course, the Scream procedure doesn't do 
  296.       anything to modify variables; more complex procedures will 
  297.       involve some fairly complex actions and testing. When you write a 
  298.       new procedure, you'll usually want to test to see if the desired 
  299.       action can be performed, and whether the things being acted upon 
  300.       are present.  
  301.          Two verbs called for by several beta-testers but not 
  302.       implemented are "shoot" and "fire," which would be useful in 
  303.       games with guns.
  304.       
  305.       
  306.       Multiple Nouns with the Same Name
  307.       ---------------------------------
  308.       One thing Infocom adventures provide are multiple nouns with the 
  309.       same name, like "brass key" and "bronze key." While GAGS 
  310.       currently doesn't provide this, it wouldn't be too difficult to 
  311.       modify it to do so. The parser would pass along the noun, but the 
  312.       Noun_Number procudure currently returns only the number of the 
  313.       first noun with the specified name. You could have Noun_Number 
  314.       check to see if the adjective matches (which would involve having 
  315.       the parser return the adjective along with the noun, verb, 
  316.       preposition, and object) and resolve unanswered ambiguities by 
  317.       asking, "Which <noun> do you mean, the <first_adj> one or the 
  318.       <second_adj> one?" 
  319.            Alternately, the parser could be left to resolve the 
  320.       ambiguity and could then return a noun NUMBER instead of the 
  321.       actual noun name. This last approach could also save some 
  322.       processor time since the noun's number is accessed during both 
  323.       the Is_Noun and the Noun_Number functions. Of course, returning a 
  324.       noun number instead of a name would require a major rewrite of 
  325.       the program. 
  326.            
  327.                                  (continued)
  328.  
  329.                                       3-7
  330.  
  331.                          (Enhancing GAGS, continued)
  332.  
  333.       Creature Animation
  334.       ------------------
  335.       With a fairly small effort, creatures in the game could be 
  336.       "animated" -- that is, made to move from room to room within the 
  337.       game. This involves modifying the ANIMATE module by adding new 
  338.       procudure(s) and making calls to them from the animate procedure. 
  339.       The procedure could check a new field in the creature record and 
  340.       thus decide what sort of motion is called for (none, random, or 
  341.       intelligent). It might merely have the creature follow the player 
  342.       once encountered, or might invoke random behavior. Perhaps 
  343.       creatures could pick up items the player has discarded (or thrown 
  344.       at the creatures), and even use them as weapons against the 
  345.       player or as tools to their own goals. There are some fascinating 
  346.       possibilities here. 
  347.  
  348.  
  349.       Turn/Time Sensitivity
  350.       ---------------------
  351.       In the same manner -- a module executed from the main program -- 
  352.       the game could support time or number-of-turn sensitivity. For 
  353.       example, the game might seal off an area of the game after a 
  354.       certain time, and trap the player inside (or outside). Or a 
  355.       creature might be added to the game after a certain time period. 
  356.       Perhaps the player could be chased more aggressively by creatures 
  357.       as time passes, or even chased at a rate commensurate (sp?) with 
  358.       his or her skill level, so experienced adventurers who breeze 
  359.       through many rooms quickly are instantly set upon by all the 
  360.       beasts available. The player might also collapse from hunger if 
  361.       s/he hasn't eaten food in a certain number of turns. Again, the 
  362.       limits for this addition are virtually limitless, but all require 
  363.       some modification of several procedures. 
  364.       
  365.  
  366.       Adding Verbs in Data Files (User-defined verbs)
  367.       --------------------------
  368.       When I first began designing GAGS, I had hoped to allow new verbs 
  369.       and their actions to be defined in the data file, so that anyone 
  370.       could add new verbs. I decided that although the idea was 
  371.       conceptually sound, the difficulty of the task made it not worth 
  372.       the advantage. Additionally, an additional level of game design 
  373.       complexity would be added. 
  374.          I think that permitting "special" verbs to be defined in data 
  375.       files is still a possibility, and though not at all a simple 
  376.       task, it would not be a lifelong effort. Essentially, my approach 
  377.       would be to add a new "special" procedure -- or more than one -- 
  378.       but leave the verb names undefined. Then, when the data file was 
  379.       read in, the verb names could be plugged into place and tested 
  380.       against. If the specified conditions of the special were in 
  381.       place, and the verb was typed, a standard "special" could be 
  382.       executed. 
  383.    
  384.  
  385.                                       3-8
  386.  
  387.  
  388.       Attempts to reduce the size of GAGS
  389.       ===================================
  390.  
  391.            The program already makes extensive use of overlay files, 
  392.       due to Turbo Pascal's 64K code segment limit. I noticed only 
  393.       about a 5-second slowdown in the game's initialization when I 
  394.       began using overlays. Since the total of the .COM file and the 
  395.       overlay files is about 75K, it's probably relatively simple to 
  396.       reduce the code size to under 64K and avoid the use of overlays, 
  397.       but I don't find a pressing need and prefer not to worry about 
  398.       the RAM needed by each feature I add.  
  399.            
  400.       Rough minimum size: 59K
  401.       -----------------------
  402.          Before GAGS grew to its present size, in an effort to further 
  403.       reduce the RAM needed, I tried adding more overlays in several 
  404.       areas. First, the main modules (execute, the two initialize 
  405.       procedures, title, and the parser) were overlaid.  This, of 
  406.       course, means a disk access every turn since the parser and 
  407.       execute procedures alternate. Then I overlaid as many of the 
  408.       EXECSUBS procedures as possible, breaking them into two or three 
  409.       overlays to avoid some disk swapping.
  410.           I then reduced the size of the arrays: to 10 creatures, 25 
  411.       nouns, and 70 rooms. This reduced the program's reported maximum 
  412.       heap size to 64K exactly.  
  413.          I then installed my machine as a 128K IBM PC, and attempted to 
  414.       run the object file with varying amounts of memory allocated to a 
  415.       print buffer (in 1K increments). 
  416.          The program, as quickly overlaid and compressed, will execute 
  417.       with a 43K print buffer installed, or in 85K of RAM. The 
  418.       operating system reserves 26K of the 85K; the program itself, 
  419.       with its data areas and such, thus takes up 59K.  
  420.          The main program .COM file was under 20K, as distinct from the 
  421.       51K file generated without use of overlays. However, even with 
  422.       all the overlays above, the standard 200-room/100-creature/100-
  423.       noun data would not fit in 128K, so there are no real savings 
  424.       except possible space reserved for other resident programs in a 
  425.       192K machine.  
  426.          These size figures were obtained before a number of GAGS' 
  427.       functions were added or enhanced; GAGS is probably about 10-20% 
  428.       larger now than it was then. Reducing GAGS to run in a 64K CP/M 
  429.       system is almost impossible, and would certainly involve too much 
  430.       performance degradation to be worth the effort.  
  431.  
  432.